package ml.tewas.gui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import ml.tewas.commondata.ForceStruct;
import ml.tewas.commondata.ThreatStruct;
import ml.tewas.util.Utilities;

public class DrawingCanvas extends JPanel {
	private static final long serialVersionUID = 1L;
	private static DrawingCanvas instance;
	private int range;
	private int dimension = 16;
	private int gridSize = 704;
	private int entitySize = 44;
	private File file;
	private int state;
	private int workingMode;

	public static final int START = 0;
	public static final int INIT = 1;
	public static final int READY = 2;
	public static final int PLAY = 3;
	public static final int PAUSE = 4;
	public static final int END_WIN = 5;
	public static final int END_LOST = 6;
	public static final int SCENARIO_END = 7;

	public static final int MANUEL_MODE = 0;
	public static final int TEST_MODE = 1;
	public static final int TRAIN_MODE = 2;

	private int agentWin = 0;
	private int agentLost = 0;

	private List<ThreatStruct> threatList = new ArrayList<ThreatStruct>();
	private List<ForceStruct> forceList = new ArrayList<ForceStruct>();

	private static final String IMAGE_ROOT = "/ml/tewas/images/";
	BufferedImage img4Destroy = null;
	BufferedImage img4Explosion = null;

	public static DrawingCanvas getInstance() {
		if (instance == null) {
			instance = new DrawingCanvas();
		}
		return instance;
	}

	private DrawingCanvas() {
		state = START;
	}

	public void paintComponent(Graphics graphics) {
		super.paintComponent(graphics);
		setBackground(new Color(1.0f, 1.0f, 1.0f));

		if (state != START && state != INIT) { // File Loads - show pearls and
												// grids only
			drawSafeZoneBackground(dimension, graphics);
			drawForces(graphics);
			drawThreats(graphics);
			drawGrids(dimension, graphics);
			Graphics2D g2d = (Graphics2D) graphics;
			g2d.setStroke(new BasicStroke(3.0f));
			drawSafeZoneGrid(dimension, graphics);
			g2d.setStroke(new BasicStroke(1.0f));
		}
	}

	private void drawThreats(Graphics graphics) {

		for (ThreatStruct threat : new ArrayList<ThreatStruct>(threatList)) {
			if (Utilities.checkPosition(threat.getPosition())) {
				graphics.drawImage(threat.getImage(), threat.getPosition()
						.getCellXPosition()
						* entitySize, threat.getPosition().getCellYPosition()
						* entitySize, this);
				if (threat.isDestroyed()) {
					graphics.drawImage(getDestroyImage(), threat.getPosition()
							.getCellXPosition()
							* entitySize, threat.getPosition()
							.getCellYPosition()
							* entitySize, this);
				}
				if (threat.isExploded()) {
					graphics.drawImage(getExplosionImage(), threat
							.getPosition().getCellXPosition()
							* entitySize, threat.getPosition()
							.getCellYPosition()
							* entitySize, this);
				}

			}

		}

	}

	private void drawForces(Graphics graphics) {

		for (ForceStruct force : forceList) {
			graphics.drawImage(force.getImage(), force.getPosition()
					.getCellXPosition()
					* entitySize, force.getPosition().getCellYPosition()
					* entitySize, this);
			if (force.isDestroyed()) {
				graphics.drawImage(getDestroyImage(), force.getPosition()
						.getCellXPosition()
						* entitySize, force.getPosition().getCellYPosition()
						* entitySize, this);

			}
		}
	}

	private void drawGrids(int n, Graphics graphics) {
		int gridSize = 704;
		range = gridSize / n;
		graphics.setColor(Color.BLACK);

		for (int i = 0; i <= gridSize; i += range) {
			graphics.drawLine(0, i, gridSize, i);
			graphics.drawLine(i, 0, i, gridSize);
		}
	}

	private void drawSafeZoneGrid(int n, Graphics graphics) {
		range = gridSize / n;
		graphics.setColor(Color.RED);
		int startPoint = range * 6;
		int endPoint = range * 10;
		graphics.drawLine(startPoint, startPoint, endPoint, startPoint);
		graphics.drawLine(startPoint, startPoint, startPoint, endPoint);
		graphics.drawLine(endPoint, startPoint, endPoint, endPoint);
		graphics.drawLine(startPoint, endPoint, endPoint, endPoint);
	}

	private void drawSafeZoneBackground(int n, Graphics graphics) {
		range = gridSize / n;
		int startPoint = range * 6;
		int width = range * 4;
		graphics.setColor(Color.YELLOW);
		graphics.fillRect(startPoint, startPoint, width, width);
	}

	public int getDimension() {
		return dimension;
	}

	public void setDimension(int dimension) {
		this.dimension = dimension;
	}

	public void setState(int state) {
		this.state = state;
	}

	public int getState() {
		return state;
	}

	public void setFile(File file) {
		this.file = file;
	}

	public File getFile() {
		return file;
	}

	public List<ThreatStruct> getThreatList() {
		return threatList;
	}

	public void setThreatList(List<ThreatStruct> threatList) {
		this.threatList = threatList;
	}

	public List<ForceStruct> getForceList() {
		return forceList;
	}

	public void setForceList(List<ForceStruct> forceList) {
		this.forceList = forceList;
	}

	private BufferedImage getDestroyImage() {

		if (img4Destroy == null) {
			String path = IMAGE_ROOT + "DESTRIOYED.png";
			URL imgURL = getClass().getResource(path);

			try {
				img4Destroy = ImageIO.read(imgURL);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return img4Destroy;
	}

	private BufferedImage getExplosionImage() {

		if (img4Explosion == null) {
			String path = IMAGE_ROOT + "EXPLOSION.jpg";
			URL imgURL = getClass().getResource(path);

			try {
				img4Explosion = ImageIO.read(imgURL);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return img4Explosion;
	}

	public int getWorkingMode() {
		return workingMode;
	}

	public void setWorkingMode(int workingMode) {
		this.workingMode = workingMode;
	}

	public void resetLists() {

		getThreatList().clear();
		getForceList().clear();
	}
	
	public void resetCounts() {
		agentLost = 0;
		agentWin = 0;;
	}

	public int getAgentWin() {
		return agentWin;
	}

	public void agentWin() {
		agentWin++;
	}

	public int getAgentLost() {
		return agentLost;
	}

	public void agentLost() {
		agentLost++;
	}
}